XDRush

深度学习中的Batch Normalization

1 背景说明

本文是同组中一位同学的组内技术分享,觉得很有意思,就暂且拿过来总结一下。涉及到的可能并不止Batch Normalization(下文简称BN),而是以BN为代表的深度学习中的网络标准化方法。

为什么深度学习网络需要标准化呢?主要原因在于输入数据的不确定性,随着训练过程的进行,导致参数震荡。网络标准化的好处主要体现在以下两个方面:

  • 加快模型的收敛速度
  • 提升模型的精度:在涉及到计算距离的算法时效果显著(距离计算如果不做标准化,就没法保证度量单位的一致性)

2 深度学习中的网络标准化

2.1 归一化

归一化的定义:将数据按比例缩放,使之落入一个特定区间,去除数据的单位限制,将其转化为无量纲的纯数值,使得数据之间具有可比性。举一个简单的例子来说明:

上图中$x_1$表示尺寸,$x_2$表示bedrooms个数,如果不做标准化,$J(\theta)$等高线如左图,做了标准化之后$J(\theta)$等高线如右图;很显然,在后续寻找梯度时,右图能更快找到最优点。

2.2 常用的归一化方法

ML/DL中常用的数据标准化方法有以下几种:
(1)min-max方法
min-max方法

(2)Log函数转换
Log函数转换

(3)atan转换

(4)Z-score转换

以上是几种常用的数据标准化的方法。BN其实也是在这几种方法的基础上演进而来的。

2.3 Batch Normalization

BN主要用来解决深度学习中的层级网络输入不一致的问题。一般情况下,深度学习优化的目标函数为:
深度学习优化目标函数

其中$\Theta$表示参数空间集合。考虑到计算量的问题,一般采用mini-batch SGD做参数更新,效果与mini-batch的大小成正比,$m$为mini-batch大小:
mini-batch大小

倘若有多层网络,假设第二层的输入为:
第二层输入

梯度下降参数更新方法如下:

如果保证$F_2$的输入分布一致,网络不用因为每一次都去适应新的分布而导致学习缓慢,话句话说就是$\Theta_2$不会剧烈震荡。

这就是BN提出的背景,本文提出的BN方法可以解决以下问题:

  • 使得各层输入的分布一致,从而加快学习过程;
  • 降低了梯度下降过程中梯度对于参数取值范围或者初始值的依赖,这将使得我们可以使用很大的学习率并且不用担心不收敛;
  • 可以去除使用dropout的必要;
  • 可以使用非线性饱和函数,因为BN使得激活函数的激活值以很大的概率落在线性区;

BN对输入数据的每一维做标准化:

$x$表示输入数据,$x^{(k)}$表示输入数据的第$k$维。假设网络中的各层的激活值分布如下图所示:
网络各层激活值分布

经过BN之后,网络各层的输入满足下面的正态分布:
各层数据经过BN之后的分布

这意味着95%的参数分布在[-2, 2]之间,对于sigmoid来讲,落入线性区的可能性更大:
sigmoid函数

以上便是BN的基本原理和解释。

3 总结

现在BN越来越流行,特别是随着数据量越来越大,在不损失模型性能的情况下,提高模型的收敛速度也就变得越来越重要了。另外,tensorflow中目前已经提供了对BN的支持,使用的也比较简单:

1
2
3
4
5
6
7
from tensorflow.contrib.layers.python.layers import batch_norm as batch_norm
# ......
bn_train = batch_norm(x, decay=self.decay, center=True, scale=True, updates_collections=None, is_training=True, reuse=None, trainable=True, scope=scope_bn)
bn_inference = batch_norm(x, decay=self.decay, center=True, scale=True, updates_collections=None, is_training=False, reuse=True, trainable=True, scope=scope_bn)